"""
Task Queue Model
任务队列模型 - 任务状态管理和进度跟踪
"""

import uuid
from enum import Enum

from sqlalchemy import Column, String, DateTime, Integer, Boolean, Text, ForeignKey, JSON
from sqlalchemy.dialects.postgresql import UUID
from sqlalchemy.sql import func
from sqlalchemy.orm import relationship

from ..core.database import Base


class TaskType(str, Enum):
    """任务类型枚举"""
    CONTENT_GENERATION = "content_generation"
    FILE_PROCESSING = "file_processing"
    BATCH_OPERATION = "batch_operation"
    SYSTEM_MAINTENANCE = "system_maintenance"
    DATA_CLEANUP = "data_cleanup"
    CONTENT_ANALYSIS = "content_analysis"


class TaskStatus(str, Enum):
    """任务状态枚举"""
    PENDING = "pending"           # 等待处理
    QUEUED = "queued"             # 已排队
    PROCESSING = "processing"     # 处理中
    COMPLETED = "completed"       # 已完成
    FAILED = "failed"             # 失败
    CANCELLED = "cancelled"       # 已取消
    TIMEOUT = "timeout"           # 超时
    RETRYING = "retrying"         # 重试中


class TaskPriority(int, Enum):
    """任务优先级枚举"""
    LOWEST = 1
    LOW = 3
    NORMAL = 5
    HIGH = 7
    HIGHEST = 9
    URGENT = 10


class TaskQueue(Base):
    """任务队列模型"""

    __tablename__ = "task_queues"

    id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
    
    # 关联信息
    user_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("users.id", ondelete="CASCADE"), 
        nullable=True,  # 系统任务可能没有用户
        index=True
    )
    
    related_content_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("generated_contents.id", ondelete="SET NULL"), 
        nullable=True,
        index=True
    )
    
    related_request_id = Column(
        UUID(as_uuid=True), 
        ForeignKey("creation_requests.id", ondelete="SET NULL"), 
        nullable=True,
        index=True
    )

    # 任务基本信息
    task_type = Column(String(50), nullable=False, index=True)
    task_name = Column(String(200), nullable=False)
    description = Column(Text, nullable=True)
    
    # 任务标识
    task_id = Column(String(100), nullable=False, unique=True, index=True)
    parent_task_id = Column(String(100), nullable=True, index=True)  # 父任务ID
    
    # 状态和优先级
    status = Column(String(20), nullable=False, default="pending", index=True)
    priority = Column(Integer, nullable=False, default=5, index=True)  # 1-10
    
    # 进度信息
    progress = Column(Integer, default=0)  # 进度百分比 (0-100)
    progress_message = Column(String(500), nullable=True)  # 进度消息
    current_step = Column(String(100), nullable=True)  # 当前步骤
    total_steps = Column(Integer, default=1)  # 总步骤数
    completed_steps = Column(Integer, default=0)  # 已完成步骤数
    
    # 重试机制
    retry_count = Column(Integer, default=0)  # 重试次数
    max_retries = Column(Integer, default=3)  # 最大重试次数
    
    # 任务参数
    task_parameters = Column(JSON, default=dict)  # 任务参数
    task_metadata = Column(JSON, default=dict)  # 任务元数据
    
    # 执行信息
    worker_id = Column(String(100), nullable=True)  # 执行的工作节点ID
    worker_type = Column(String(50), nullable=True)  # 工作节点类型
    execution_host = Column(String(100), nullable=True)  # 执行主机
    execution_pid = Column(Integer, nullable=True)  # 执行进程ID
    
    # 时间信息
    created_at = Column(DateTime, default=func.now(), index=True)
    updated_at = Column(DateTime, default=func.now(), onupdate=func.now())
    queued_at = Column(DateTime, nullable=True)  # 排队时间
    started_at = Column(DateTime, nullable=True)  # 开始执行时间
    completed_at = Column(DateTime, nullable=True)  # 完成时间
    
    # 超时设置
    timeout_seconds = Column(Integer, nullable=True)  # 超时时间（秒）
    estimated_duration = Column(Integer, nullable=True)  # 预估执行时间（秒）
    
    # 结果信息
    result_data = Column(JSON, nullable=True)  # 执行结果
    error_message = Column(Text, nullable=True)  # 错误信息
    error_code = Column(String(50), nullable=True)  # 错误代码
    error_details = Column(JSON, nullable=True)  # 错误详情
    
    # 资源使用
    memory_usage_mb = Column(Integer, nullable=True)  # 内存使用（MB）
    cpu_usage_percent = Column(Integer, nullable=True)  # CPU使用百分比
    
    # 成本信息
    estimated_cost = Column(Integer, nullable=True)  # 预估成本（分）
    actual_cost = Column(Integer, nullable=True)  # 实际成本（分）
    
    # 依赖关系
    depends_on_task_ids = Column(JSON, default=list)  # 依赖的任务ID列表
    
    # 调度信息
    scheduled_at = Column(DateTime, nullable=True)  # 计划执行时间
    cron_expression = Column(String(100), nullable=True)  # Cron表达式（定时任务）
    
    # 过期和清理
    expires_at = Column(DateTime, nullable=True)  # 过期时间
    retention_days = Column(Integer, default=30)  # 保留天数
    
    # 关系
    user = relationship("User", back_populates="task_queues")
    related_content = relationship("GeneratedContent", back_populates="task_queues")
    related_request = relationship("CreationRequest", back_populates="task_queues")
    child_tasks = relationship(
        "TaskQueue", 
        remote_side=[id], 
        foreign_keys=[parent_task_id],
        backref="parent_task"
    )
    system_logs = relationship("SystemLog", back_populates="related_task")

    def __repr__(self):
        return f"<TaskQueue(id={self.id}, task_id={self.task_id}, type={self.task_type}, status={self.status})>"

    @property
    def is_pending(self) -> bool:
        """是否等待中"""
        return self.status == TaskStatus.PENDING

    @property
    def is_processing(self) -> bool:
        """是否处理中"""
        return self.status == TaskStatus.PROCESSING

    @property
    def is_completed(self) -> bool:
        """是否已完成"""
        return self.status == TaskStatus.COMPLETED

    @property
    def is_failed(self) -> bool:
        """是否失败"""
        return self.status == TaskStatus.FAILED

    @property
    def is_cancelled(self) -> bool:
        """是否已取消"""
        return self.status == TaskStatus.CANCELLED

    @property
    def is_retrying(self) -> bool:
        """是否重试中"""
        return self.status == TaskStatus.RETRYING

    @property
    def can_retry(self) -> bool:
        """检查是否可以重试"""
        return (
            self.status in [TaskStatus.FAILED, TaskStatus.TIMEOUT, TaskStatus.CANCELLED] and
            self.retry_count < self.max_retries
        )

    @property
    def is_expired(self) -> bool:
        """检查是否已过期"""
        if not self.expires_at:
            return False
        from datetime import datetime
        return datetime.utcnow() > self.expires_at

    @property
    def processing_time_seconds(self) -> int:
        """获取处理时间（秒）"""
        if not self.started_at or not self.completed_at:
            return 0
        return int((self.completed_at - self.started_at).total_seconds())

    @property
    def queue_time_seconds(self) -> int:
        """获取排队时间（秒）"""
        if not self.queued_at or not self.started_at:
            return 0
        return int((self.started_at - self.queued_at).total_seconds())

    @property
    def total_time_seconds(self) -> int:
        """获取总时间（秒）"""
        if not self.created_at or not self.completed_at:
            return 0
        return int((self.completed_at - self.created_at).total_seconds())

    @property
    def step_progress(self) -> float:
        """获取步骤进度（0-100）"""
        if self.total_steps <= 0:
            return 0.0
        return (self.completed_steps / self.total_steps) * 100

    def update_progress(self, progress: int, message: str = None) -> None:
        """更新进度"""
        self.progress = max(0, min(100, progress))
        if message:
            self.progress_message = message

    def update_step_progress(self, current_step: int, total_steps: int = None, message: str = None) -> None:
        """更新步骤进度"""
        self.completed_steps = current_step
        if total_steps is not None:
            self.total_steps = total_steps
        if message:
            self.current_step = message
        
        # 更新总体进度
        if self.total_steps > 0:
            self.progress = int((self.completed_steps / self.total_steps) * 100)

    def mark_as_queued(self) -> None:
        """标记为已排队"""
        self.status = TaskStatus.QUEUED
        self.queued_at = func.now()
        self.progress = 0

    def mark_as_started(self, worker_id: str = None, worker_type: str = None) -> None:
        """标记为开始处理"""
        self.status = TaskStatus.PROCESSING
        self.started_at = func.now()
        if worker_id:
            self.worker_id = worker_id
        if worker_type:
            self.worker_type = worker_type
        self.progress = 0
        self.completed_steps = 0

    def mark_as_completed(self, result_data: dict = None) -> None:
        """标记为完成"""
        self.status = TaskStatus.COMPLETED
        self.completed_at = func.now()
        self.progress = 100
        if result_data:
            self.result_data = result_data

    def mark_as_failed(self, error_message: str, error_code: str = None, error_details: dict = None) -> None:
        """标记为失败"""
        self.status = TaskStatus.FAILED
        self.completed_at = func.now()
        self.error_message = error_message
        if error_code:
            self.error_code = error_code
        if error_details:
            self.error_details = error_details

    def mark_as_cancelled(self) -> None:
        """标记为已取消"""
        self.status = TaskStatus.CANCELLED
        self.completed_at = func.now()
        self.progress = 0

    def mark_as_timeout(self) -> None:
        """标记为超时"""
        self.status = TaskStatus.TIMEOUT
        self.completed_at = func.now()
        self.error_message = "任务执行超时"

    def mark_as_retrying(self) -> None:
        """标记为重试中"""
        self.status = TaskStatus.RETRYING
        self.retry_count += 1
        self.progress = 0

    def increment_retry(self) -> None:
        """增加重试次数"""
        self.retry_count += 1

    def set_resource_usage(self, memory_mb: int = None, cpu_percent: int = None) -> None:
        """设置资源使用情况"""
        if memory_mb is not None:
            self.memory_usage_mb = memory_mb
        if cpu_percent is not None:
            self.cpu_usage_percent = cpu_percent

    def set_cost(self, estimated_cost: int = None, actual_cost: int = None) -> None:
        """设置成本信息"""
        if estimated_cost is not None:
            self.estimated_cost = estimated_cost
        if actual_cost is not None:
            self.actual_cost = actual_cost

    def add_dependency(self, task_id: str) -> None:
        """添加依赖任务"""
        dependencies = self.depends_on_task_ids or []
        if task_id not in dependencies:
            dependencies.append(task_id)
            self.depends_on_task_ids = dependencies

    def remove_dependency(self, task_id: str) -> bool:
        """移除依赖任务"""
        dependencies = self.depends_on_task_ids or []
        if task_id in dependencies:
            dependencies.remove(task_id)
            self.depends_on_task_ids = dependencies
            return True
        return False

    def has_dependencies(self) -> bool:
        """检查是否有依赖任务"""
        return bool(self.depends_on_task_ids)

    def can_execute(self, completed_task_ids: set) -> bool:
        """检查是否可以执行（依赖是否都已完成）"""
        if not self.depends_on_task_ids:
            return True
        
        dependencies = set(self.depends_on_task_ids)
        return dependencies.issubset(completed_task_ids)

    def is_ready_for_cleanup(self) -> bool:
        """检查是否已准备好清理"""
        from datetime import datetime, timedelta
        
        if not self.completed_at:
            return False
        
        # 检查保留期
        cutoff_date = self.completed_at + timedelta(days=self.retention_days)
        return datetime.utcnow() > cutoff_date

    def to_dict(self) -> dict:
        """转换为字典"""
        return {
            "id": str(self.id),
            "task_id": self.task_id,
            "task_type": self.task_type,
            "task_name": self.task_name,
            "description": self.description,
            "status": self.status,
            "priority": self.priority,
            "progress": self.progress,
            "progress_message": self.progress_message,
            "current_step": self.current_step,
            "total_steps": self.total_steps,
            "completed_steps": self.completed_steps,
            "retry_count": self.retry_count,
            "max_retries": self.max_retries,
            "worker_id": self.worker_id,
            "worker_type": self.worker_type,
            "created_at": self.created_at.isoformat() if self.created_at else None,
            "started_at": self.started_at.isoformat() if self.started_at else None,
            "completed_at": self.completed_at.isoformat() if self.completed_at else None,
            "processing_time": self.processing_time_seconds,
            "queue_time": self.queue_time_seconds,
            "total_time": self.total_time_seconds,
            "result_data": self.result_data,
            "error_message": self.error_message,
            "error_code": self.error_code,
            "memory_usage_mb": self.memory_usage_mb,
            "cpu_usage_percent": self.cpu_usage_percent,
            "estimated_cost": self.estimated_cost,
            "actual_cost": self.actual_cost,
        }